////////////////////////////////////////////////////////////////////////////////
//      
//      Kingsoft File for shp routines file
//      
//      File      : she_res.h
//      Comment   : shp Resources manager
//					
//      Create at : 2012-12-07 10:17:25
//      Create by : chenguicheng
//      
////////////////////////////////////////////////////////////////////////////////

#pragma once
#include <atlcoll.h>
#include "shp_def.h"
#include "shp_style.h"
#include "shp_skin.h"
#include "shp_path.h"
#include "common/shp_draw.h"

#define SHP_MAKEKEY(b_bold, b_underline, b_italic, n_size) (WORD)((n_size<<8) | ((int)b_bold<<2) | ((int)b_underline<<1) | (int)b_italic )

#define SHP_ISBOLD(key)         (key & 0x0004) 
#define SHP_ISUNDERLINE(key)    (key & 0x0002)
#define SHP_ISITALIC(key)       (key & 0x0001)
#define SHP_GETSIZE(key)		(key >> 8 )

class shp_gdi_plus
{
public:
	shp_gdi_plus() throw()
		: m_dw_token(0)
	{}

	~shp_gdi_plus() throw()
	{}

	static shp_gdi_plus& Instance()
	{
		static shp_gdi_plus _obj;
		return _obj;
	}

	void init()
	{
		assert( m_dw_token == 0 );
		Gdiplus::GdiplusStartupInput input;
		Gdiplus::GdiplusStartupOutput output;
		Gdiplus::Status status = Gdiplus::GdiplusStartup( &m_dw_token, &input, &output );
	}

	void un_init()
	{
		Gdiplus::GdiplusShutdown( m_dw_token );
	}

private:
	ULONG_PTR m_dw_token;
};


class shp_font_mgr
{
public:
	shp_font_mgr()
	:m_i_fontsize(-12)
	{
		
	}

	~shp_font_mgr()
	{
		
	}

	static shp_font_mgr& Instance()
	{
		static shp_font_mgr _obj;
		return _obj;
	}

	void un_init()
	{
		POSITION pos = m_map_font.GetStartPosition();
		while (pos != NULL) 
		{
			shpfont font =  m_map_font.GetNextValue(pos);
			shp_draw::destroy_font( font );		
		}

		m_map_font.RemoveAll();
	}

	void set_def_info( shpstr& str_font, int n_size )
	{
		m_str_face = str_font;
		m_i_fontsize = n_size;
	}

	shpfont get_font( bool b_bold, bool b_underline, bool b_italic, int n_size )
	{
		WORD w_key = SHP_MAKEKEY( b_bold, b_underline, b_italic, n_size );
		return get_font( w_key );
	}

	shpfont get_def_font()
	{
		return get_font( 0 );
	}

	shpfont get_font( WORD w_key )
	{
		CAtlMap<WORD, shpfont >::CPair* p_font = m_map_font.Lookup( w_key );
		if( p_font )
			return p_font->m_value;
		else
		{
			shpfont font = shp_draw::create_new_font( (BOOL)SHP_ISBOLD(w_key), (BOOL)SHP_ISUNDERLINE(w_key), 
							(BOOL)SHP_ISITALIC(w_key), m_i_fontsize+SHP_GETSIZE(w_key), m_str_face );
			m_map_font[w_key] = font;
			return font;
		}
	}


protected:

	int							m_i_fontsize;
	shpstr						m_str_face;
	CAtlMap<WORD, shpfont>		m_map_font;

};


class shp_style_mgr
{
public:
	shp_style_mgr()
	{

	}

	~shp_style_mgr()
	{
		
	}

	void un_init()
	{
		POSITION pos = m_map_style.GetStartPosition();
		while ( pos != NULL ) 
		{
			shp_style* p_style = m_map_style.GetNextValue( pos );
			if( p_style )
				delete p_style;
		}

		m_map_style.RemoveAll();
	}

	static shp_style_mgr& Instance()
	{
		static shp_style_mgr _obj;
		return _obj;
	}

	inline shp_style* get_style( shpstr& str_type )
	{
		CAtlMap<shpstr, shp_style*>::CPair *p_find = m_map_style.Lookup( str_type );
		if( p_find )
			return p_find->m_value;

		return NULL;
	}

	void add_style( shpstr& str_type, shp_style* p_style )
	{
		if( p_style == NULL )
			return;

		shp_style* p_find = get_style( str_type );
		if( p_find )
			delete p_find;

		m_map_style.SetAt( str_type, p_style );
	}

protected:

	CAtlMap<shpstr, shp_style*>		m_map_style;

};


class shp_skin_mgr
{
public:
	shp_skin_mgr()
	{

	}

	~shp_skin_mgr()
	{
		
	}

	void un_init()
	{
		POSITION pos = m_map_skin.GetStartPosition();
		while ( pos != NULL ) 
		{
			shp_skin* p_skin = m_map_skin.GetNextValue( pos );
			if( p_skin )
				delete p_skin;
		}

		m_map_skin.RemoveAll();
	}

	static shp_skin_mgr& Instance()
	{
		static shp_skin_mgr _obj;
		return _obj;
	}

	inline shp_skin* get_skin( shpstr& str_skin )
	{
		CAtlMap<shpstr, shp_skin*>::CPair *p_find = m_map_skin.Lookup( str_skin );
		if( p_find )
			return p_find->m_value;

		return NULL;
	}

	void add_skin( shpstr& str_skin, shp_skin* p_skin )
	{
		if( p_skin == NULL )
			return;

		shp_skin* p_find = get_skin( str_skin );
		if( p_find )
			delete p_find;

		m_map_skin.SetAt( str_skin, p_skin );
	}

	void draw( shpdc& dc, int i_state, shpstr& str_skin, CRect& rect, CRect& draw_rect, bool b_calc )
	{
		shp_skin* p_skin = get_skin( str_skin );

		if( p_skin )
			p_skin->draw( dc, i_state, rect, draw_rect );

		if( b_calc && p_skin )
		{
			CSize size = p_skin->get_skin_size();
			rect.right = rect.left + size.cx;
			rect.bottom = rect.top + size.cy;
		}
	}

protected:

	CAtlMap<shpstr, shp_skin*>		m_map_skin;

};